package org.wevil.service;

import org.wevil.entity.news.NewsSubject;
import org.wevil.repo.CondRoleSubjectRepo;
import org.wevil.repo.NewsSubjectRepo;
import org.wevil.service.sys.RoleService;
import org.wevil.util.BeanUtil;
import org.wevil.vo.list.SubjectListVo;
import org.wevil.vo.node.SubjectNodeVo;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
@Transactional
public class SubjectService {

    @Resource
    NewsSubjectRepo repo;
    @Resource
    RoleService roleService;
    @Resource
    CondRoleSubjectRepo condRoleSubjectRepo;

    /** 获取用户栏目列表 */
    public List<SubjectListVo> userList(Integer userId) {
        List<SubjectListVo> list = all();
        if(userId != 1){
            // 根据角色判断，对应角色只能看到自己角色的菜单
            List<Integer> roleIds = roleService.getRoleIdListByUserId(userId);
            List<Integer> subjectIds = getSubjectIdsByRoleIds(roleIds);
            list = list.stream().filter(node -> subjectIds.contains(node.getId())).collect(Collectors.toList());
        }
        return list;
    }

    /**
     * 获取角色拥有的栏目
     * */
    public List<Integer> getSubjectIdsByRoleIds(List<Integer> roleIds) {
        return condRoleSubjectRepo.findSubjectIdByRoleIdIn(roleIds);
    }

    /** 获取用户栏目节点 */
    public List<SubjectNodeVo> userNode(Integer userId) {
        List<SubjectNodeVo> list = node();
        // 再根据角色判断，对应角色只能看到自己角色的菜单
        if(userId != 1){
            List<Integer> roleIds = roleService.getRoleIdListByUserId(userId);
            List<Integer> subjectIds = getSubjectIdsByRoleIds(roleIds);
            list = list.stream().filter(node -> subjectIds.contains(node.getId())).collect(Collectors.toList());
        }
        return list;
    }

    /** 获取所有栏目 */
    public List<SubjectListVo> all() {
        List<NewsSubject> all = repo.findAll();
        List<SubjectListVo> vos = new ArrayList<>();
        all.forEach(subject -> {
            NewsSubject entity = convertName(subject);
            vos.add(entity2vo(entity));
        });
        return vos;
    }

    /** 获取一个栏目下的所有子栏目id */
    public List<Integer> getSubId(Integer subjectId){
        Optional<NewsSubject> opt1 = repo.findById(subjectId);
        List<NewsSubject> list = new ArrayList<>();
        if(opt1.isPresent()){
            NewsSubject entity1 = opt1.get();
            list.add(entity1);
            // 获取子栏目数据
            getSub(entity1.getId(), list);
            // 转换数据
            List<Integer> vos = new ArrayList<>();
            list.forEach(subject -> {
                vos.add(subject.getId());
            });
            return vos;
        }
        return null;
    }

    /** 获取一个栏目下的所有子栏目 */
    public List<SubjectListVo> getSubById(Integer subjectId){
        Optional<NewsSubject> opt1 = repo.findById(subjectId);
        List<NewsSubject> list = new ArrayList<>();
        if(opt1.isPresent()){
            NewsSubject entity1 = opt1.get();
            //list.add(entity1);
            // 获取子栏目数据
            getSub(entity1.getId(), list);
            // 转换数据
            List<SubjectListVo> vos = new ArrayList<>();
            list.forEach(subject -> {
                NewsSubject entity = convertName(subject);
                vos.add(entity2vo(entity));
            });
            return vos;
        }
        return null;
    }

    /**
     * 获取一个栏目下的所有子节点栏目
     * */
    public List<SubjectNodeVo> getSubNodeById(Integer subjectId){
        Optional<NewsSubject> opt1 = repo.findById(subjectId);
        List<NewsSubject> list = new ArrayList<>();
        List<SubjectNodeVo> vos = new ArrayList<>();
        if(opt1.isPresent()){
            NewsSubject entity1 = opt1.get();
            NewsSubject newEntity = new NewsSubject();
            BeanUtil.copyPropIgnoreNull(entity1, newEntity);
            newEntity.setPid(0);
            list.add(newEntity);
            // 获取子栏目数据
            getSub(newEntity.getId(), list);
            if(list.size()>1){
                // 转换数据
                list.forEach(entity -> vos.add(entity2NodeVo(entity)));
            }
        }
        return vos;
    }

    /** 所有栏目节点数据 */
    public List<SubjectNodeVo> node() {
        List<NewsSubject> list = repo.findAll();
        List<SubjectNodeVo> vos = new ArrayList<>();
        list.forEach(entity -> vos.add(entity2NodeVo(entity)));
        return vos;
    }

    /** 栏目名称拼接父栏目名称 */
    public NewsSubject convertName(NewsSubject entity){
        int subjectId = entity.getId();
        String subjectName = entity.getName();
        Integer pid = entity.getPid();
        if(pid != 0){
            NewsSubject newsSubject = repo.findById(pid).get();
            String pName = newsSubject.getName() + "-" + subjectName;
            Integer pid1 = newsSubject.getPid();
            NewsSubject temp = new NewsSubject();
            temp.setId(subjectId);
            temp.setName(pName);
            temp.setPid(pid1);
            return convertName(temp);
        }
        else{
            // 将上面递归里修改的pid改为原来栏目本身的pid
            Integer pid1 = repo.findById(entity.getId()).get().getPid();
            entity.setPid(pid1);
        }
        return entity;
    }

    /** 获取子栏目 */
    public void getSub(Integer subId, List<NewsSubject> list){
        // 获取有没有子栏目
        List<NewsSubject> sub1List = repo.findByPid(subId);
        if(sub1List!=null && sub1List.size()>0){
            for(NewsSubject sub : sub1List){
                list.add(sub);
                getSub(sub.getId(), list);
            }
        }
    }

    /** 实体转vo */
    public SubjectListVo entity2vo(NewsSubject entity) {
        SubjectListVo vo = new SubjectListVo();
        BeanUtil.copyPropIgnoreNull(entity, vo);
        return vo;
    }

    /**
     * 实体转vo
     * */
    private SubjectNodeVo entity2NodeVo(NewsSubject entity){
        SubjectNodeVo vo = new SubjectNodeVo();
        BeanUtil.copyPropIgnoreNull(entity, vo);
        vo.setId(entity.getId());
        vo.setName(entity.getName());
        return vo;
    }
}
